import time
import pygame
from random import randint, random
from pygame.locals import *
import math

# pygame初始化
pygame.init()
# 添加字体，使用系统字体
font = pygame.font.Font("C:/Windows/Fonts/simhei.ttf", 24)  # 通过字体文件获得字体对象
# 设定屏幕大小
screen = pygame.display.set_mode(size=[480, 580])
point_list = []
times = 1


def get_rand_point(startx, endx, starty, endy):
    '''
    根据指定的范围生成随机的坐标点
    '''
    return tuple((random() * (endx - startx) + startx, random() * (endy - starty) + starty))


class RandColor(pygame.Color):
    '''
    随机颜色类，直接调用构造函数生成一个随机的pygame.Color
    '''

    def __init__(self):
        super().__init__(randint(0, 255), randint(0, 255), randint(0, 255))


def draw_border():
    '''
    绘制随机边框
    :return:
    '''
    global screen
    pygame.draw.circle(screen, (255, 255, 255), (240, 240), 240, 1)
    pygame.display.update()


def draw_rand_point(num: int):
    global screen
    # 生成随机点，直到数量达到num
    while len(point_list) < num:
        point = get_rand_point(0, 480, 0, 480)
        point_list.append(point)
        pygame.draw.rect(screen, RandColor(), [int(point[0]), int(point[1]), 1, 1], 1)
    # 绘制边框
    draw_border()
    # 更新屏幕
    pygame.display.update()


def event_handle():
    '''
    pygame事件处理
    :return:
    '''
    global screen, times
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
        elif event.type == KEYDOWN:
            pressed_key = pygame.key.get_pressed()
            # 按下空格键开始解算
            if pressed_key[K_SPACE]:
                draw_rand_point(2 ** times)
                # 计算在圆内的点的个数
                inner_count = len([i for i in point_list if math.sqrt((i[0] - 240) ** 2 + (i[1] - 240) ** 2) < 240])
                text("已经绘制%d个随机点" % len(point_list), [0, 480])
                text("在圆内点的个数为：%d" % inner_count, [0, 510])
                text("估算圆周率为：%f" % (inner_count / len(point_list) * 4), [0, 540])
                times += 1


def text(msg: str, pos):
    global font, screen
    textSurfaceObj = font.render(msg, True, 'white', 'black')  # 配置要显示的文字
    # 绘制文字到屏幕上
    screen.blit(textSurfaceObj, pos)


if __name__ == '__main__':
    draw_border()
    while True:
        event_handle()
        time.sleep(0.01)
